package samber

import (
	"fmt"
	"github.com/samber/lo"
	"strconv"
	"time"
)

// FanIn 多个父管道吐到子管道里面
func FanIn() {
	upstream1 := make(chan string, 2)
	upstream2 := make(chan string, 2)
	upstream1 <- "1"
	upstream1 <- "2"
	upstream2 <- "3"
	channelBufferCap := 5
	downstream := lo.FanIn(channelBufferCap, upstream1, upstream2)
	time.Sleep(1 * time.Second)                            // 图简单 防止死锁记得在必要的业务逻辑里面关掉
	fmt.Printf("%v len %v\n", downstream, len(downstream)) // 3
}

// FanOut 思路借鉴上面
func FanOut() {
	fmt.Println("FanOut 所有上游消息广播到多个下游通道。当上游通道达到EOF时，下游通道关闭。如果任何下游通道已满，则暂停广播。")
}

type foo struct {
	bar  string
	fill string
}

func (f foo) Clone() foo {
	return foo{fill: f.fill}
}

// Fill 填充默认值
func Fill() {
	list := []foo{{bar: "a"}, {bar: "a"}, {bar: "a", fill: "c"}}
	result := lo.Fill[foo](list, foo{fill: "x"})
	fmt.Printf("%v \n", result) // [{ x} { x} { x}]
}

// Filter 相当于where
func Filter() {
	list := []int64{1, 2, 3, 4}
	result := lo.Filter(list, func(nbr int64, index int) bool {
		return nbr%2 == 0
	})
	fmt.Printf("%v \n", result) // [2 4]

	listStruct := []foo{{bar: "1"}, {bar: "2"}}
	res := lo.Filter(listStruct, func(nbr foo, index int) bool {
		return nbr.bar == "1"
	})
	fmt.Printf("%v \n", res) // [{1 }]
}

// FilterMap 比Filter多了个类似于可以在里面处理值
func FilterMap() {
	list := []int64{1, 2, 3, 4}

	result := lo.FilterMap(list, func(nbr int64, index int) (int64, bool) {
		return nbr * 2, nbr%2 == 0
	})
	fmt.Printf("%v \n", result) // [4 8]
}

func Find() {
	list := []int64{1, 2, 3, 4}
	result, ok := lo.Find(list, func(item int64) bool {
		return item == 2
	})
	fmt.Printf("%v %v\n", result, ok) // 2 true
}

// FindDuplicates 找出存在重复的值
func FindDuplicates() {
	list := []int64{1, 1, 2, 3, 3, 4}
	result := lo.FindDuplicates(list)
	fmt.Printf("%v \n", result) // [1 3]
}

// FindDuplicatesBy 每个值做自己写的逻辑之后再取重复原值出来
func FindDuplicatesBy() {
	list := []int64{1, 1, 2, 3, 3, 4}
	result := lo.FindDuplicatesBy(list, func(item int64) int {
		return int(item * item)
	})
	fmt.Printf("%v \n", result) // [1 3]
}

// FindIndexOf 找第一个出现的值并得到值、下标、是否存在
func FindIndexOf() {
	list := []int64{1, 1, 2, 3, 3, 4}
	result, index, exist := lo.FindIndexOf(list, func(item int64) bool {
		return item == 1
	})
	fmt.Printf("%v %v %v\n", result, index, exist) // 1 0 true
}

// FindKey 根据Map的顺序来value反找最新的key
func FindKey() {
	demo := map[string]int{
		"1": 1,
		"2": 2,
		"3": 1,
	}
	key, exist := lo.FindKey(demo, 1)
	fmt.Printf("%v %v\n", key, exist) // 3 true
}

// FindLastIndexOf FindIndexOf相对找最新出现的
func FindLastIndexOf() {
	list := []int64{1, 1, 2, 3, 3, 4}
	result, index, exist := lo.FindLastIndexOf(list, func(item int64) bool {
		return item == 1
	})
	fmt.Printf("%v %v %v\n", result, index, exist) // 1 1 true
}

// FindOrElse 找不到给个默认值
func FindOrElse() {
	list := []int64{1, 1, 2, 3, 3, 4}
	result := lo.FindOrElse(list, 99, func(item int64) bool {
		return item == 5
	})
	fmt.Printf("%v\n", result) // 99
}

// FindUniques 找到数组中只出现一次的
func FindUniques() {
	list := []int64{1, 1, 2, 3, 3, 4}
	result := lo.FindUniques(list)
	fmt.Printf("%v\n", result) // [2, 4]
}

// FindUniquesBy 每个值做自己写的逻辑之后再取唯一的话将原值出来
func FindUniquesBy() {
	list := []int64{1, 1, 2, 3, 3, 4}
	result := lo.FindUniquesBy(list, func(item int64) int {
		return int(item * item)
	})
	fmt.Printf("%v\n", result) // [2, 4]
}

// FlatMap 操作切片转并外一种切片
func FlatMap() {
	list := []int64{1, 2, 3, 4}
	result := lo.FlatMap(list, func(nbr int64, index int) []string {
		return []string{
			strconv.FormatInt(nbr, 10), // base 10
			strconv.FormatInt(nbr, 2),  // base 2
		}
	})
	fmt.Printf("%v\n", result) // [1 1 2 10 3 11 4 100]
}

// Flatten 降维数组
func Flatten() {
	list := [][]int{{0, 1, 2}, {3, 4, 5}}
	result := lo.Flatten(list)
	fmt.Printf("%v\n", result) // [0 1 2 3 4 5]
}

// ForEach 遍历一遍
func ForEach() {
	var newList []int64
	list := []int64{1, 2, 3, 4}
	lo.ForEach(list, func(x int64, index int) {
		newList = append(newList, x)
		x = x * 2 // 里面修改无效
	})
	fmt.Printf("%v %v\n", newList, list) // [1 2 3 4] [1 2 3 4]
}

// FromAnySlice 满足断言则一口气转类型
func FromAnySlice() {
	slice2 := []interface{}{"1", "2"}
	result, ok := lo.FromAnySlice[string](slice2)
	fmt.Printf("%v %v \n", result, ok) // [1 2] true
}

// FromEntries 将键/值对数组转换为映射
func FromEntries() {
	result := lo.FromEntries([]lo.Entry[string, int]{
		{
			Key:   "foo",
			Value: 1,
		},
		{
			Key:   "bar",
			Value: 2,
		},
		{
			Key:   "baz",
			Value: 3,
		},
	})
	fmt.Printf("%v\n", result) // map[bar:2 baz:3 foo:1]
}

func FromPairs() {
	fmt.Println("FromPairs 的别名")
}

// FromPtr 取指针下的值
func FromPtr() {
	var demo *foo
	demo = &foo{
		bar:  "1",
		fill: "2",
	}
	res := lo.FromPtr(demo)
	fmt.Printf("%v\n", res)
}

// FromPtrOr 取指针下的值，nil则是默认值
func FromPtrOr() {
	var demo *foo
	res := lo.FromPtrOr(demo, foo{bar: "init"})
	fmt.Printf("%v\n", res)
}
